﻿using Digitalmes.Application.Common.Behaviours;
using Digitalmes.Application.Common.PublishStrategies;
using Digitalmes.Application.Common.BusinessPolicies;

namespace Digitalmes.Application;

public static class DependencyInjection
{
    public static void AddApplicationSetup(this IHostBuilder builder)
    {
        builder.ConfigureServices((hostBuilder, services) =>
        {
            services.AddValidators();
            services.AddMediatR();
            services.AddMapper();
            services.AddApplicationService();
            services.AddBusinessPolicy();
        });
    }

    /// <summary>
    /// 添加 FluentValidation 验证器。
    /// </summary>
    /// <param name="services"></param>
    private static void AddValidators(this IServiceCollection services)
    {
        services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
    }

    private static void AddMediatR(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient)
    {
        services.AddMediatR(cfg =>
        {
            cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());

            cfg.Lifetime = lifetime;

            // Request 请求会按 PipelineBehavior 注册顺序逆序排序后包裹执行。
            cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>), lifetime);
            cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>), lifetime);
            cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>), lifetime);
            cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>), lifetime);

            // 默认是框架自带的 ForeachAwaitPublisher，可以调整为 TaskWhenAllPublisher
            cfg.NotificationPublisher = PublishStrategyFactory.Create(PublishStrategy.ParallelNoWait); // 不能带任何任务结果
        });
    }

    /// <summary>
    /// 设置对象映射配置策略。
    /// </summary>
    /// <returns></returns>
    private static void AddMapper(this IServiceCollection services)
    {
        TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(NameMatchingStrategy.Flexible); // 属性名称不区分大小写
        TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true); // 保留引用关系

        services.AddMapster();
    }

    /// <summary>
    /// 注册 <see cref="IApplicationService"/> 应用服务。
    /// </summary>
    private static void AddApplicationService(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient)
    {
        var types = typeof(DependencyInjection).Assembly.GetAllTypesOf<IApplicationService>();
        foreach (var type in types)
        {
            var @interface = type.GetInterfaces().Single(s => s != typeof(IApplicationService));
            services.TryAdd(new ServiceDescriptor(@interface, type, lifetime));
        }
    }

    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="services"></param>
    private static void AddBusinessPolicy(this IServiceCollection services)
    {
        //services.AddSingleton<IPolicyRegisterFactory, PolicyRegisterFactory>();

        var policyTypes = typeof(DependencyInjection).Assembly.GetAllTypesOf<IBusinessPolicy>();
        foreach (var policyType in policyTypes)
        {
            services.RegisterBusinessPolicy(policyType);
        }
    }
}
